package com.hjb.service.gateway.hyl.impl;

import com.hjb.service.config.properties.HYLProperties;
import com.hjb.service.gateway.hyl.HylService;
import com.hjb.service.gateway.hyl.base.HYLResponseVO;
import com.hjb.service.gateway.hyl.util.EncryDecryUtils;
import com.hjb.service.gateway.hyl.util.FormDateReportConvertor;
import com.hjb.service.utils.MapUtil;
import com.hjb.service.utils.MySSLProtocolSocketFactory;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;


/**
 * Created by gy on 2017/7/26.
 * 好易联接口实现
 */
@Service("hylService")
public class HylServiceImpl implements HylService{

	private Logger log = LoggerFactory.getLogger(getClass());
	@Autowired
	private HYLProperties hylProperties;

	@Override
	public HYLResponseVO submitVerify(Map<String, String> request) {
		HYLResponseVO hylResponseVO = new HYLResponseVO();
		String resultStr = null;
		try {
			//获取请求对象
			Map<String, String> params = getVerifyMap(request);
			params.put("idCardName", URLEncoder.encode(params.get("idCardName"),"UTF-8"));
			//获取请求message
			String message = getMessage(params);
			//封装参数
			NameValuePair[] param = {
					new NameValuePair("source", "01"),  //01此值不需要改变
					new NameValuePair("msgFlag", "0"),  //短信下发标志0-不下发 1-下发
					new NameValuePair("type","02"),     //01身份验证 02卡信息验证
					new NameValuePair("message", message)
			};
			log.info("好易联鉴权请求地址:"+hylProperties.getVerifyurl());
			//发送请求
			resultStr = sendRequest(param,hylProperties.getVerifyurl());
			log.info("好易联鉴权返回加密报文"+resultStr);
			if (StringUtils.isBlank(resultStr)){
				hylResponseVO.setResponseCode(MapUtil.INTF_ERR_CODE);
				hylResponseVO.setMessage("好易联鉴权请求错误");
				return hylResponseVO;
			}
		} catch (Exception e) {
			log.info("好易联鉴权请求错误："+e);
			hylResponseVO.setResponseCode(MapUtil.INTF_ERR_CODE);
			hylResponseVO.setMessage("好易联鉴权请求错误");
			return hylResponseVO;
		}
		if(resultStr.split("\\|").length==2){
			String return2 = resultStr.split("\\|")[1];
			//错误原因
			hylResponseVO.setResponseCode(MapUtil.INTF_ERR_CODE);
			hylResponseVO.setResponseMsg(EncryDecryUtils.base64Decrypt(return2));
			return hylResponseVO;
		}
		//处理响应报文
		String return1 = resultStr.split("\\|")[0];
		String return2 = resultStr.split("\\|")[1];
		String return3 = resultStr.split("\\|")[2];
		//解析第二部分，获取原始报文 先解密base再解密3des
		String originalMsg  =  EncryDecryUtils.decryptFromBase64DES(hylProperties.getDes3Key(), return2);
		String result = null;
		try {
			result = URLDecoder.decode(originalMsg,"utf-8");
			log.info("好易联鉴权返回的报文明文是:"+result);
			String originalSign  =  EncryDecryUtils.base64Decrypt(return3);
			log.info("好易联鉴权返回的报文原始签名是:"+ originalSign);
			//报文验签
			boolean signFlag = verifySign(originalMsg,originalSign);
			hylResponseVO.setVerifySignFlag(signFlag);
		} catch (UnsupportedEncodingException e) {
			log.info("好易联鉴权请求返回结果转码错误："+e);
			hylResponseVO.setResponseCode(MapUtil.INTF_ERR_CODE);
			hylResponseVO.setResponseMsg("好易联鉴权失败");
			return hylResponseVO;
		}
		//获取验证状态
		if (StringUtils.isNotBlank(result)){

			String orderState = result.substring(result.indexOf("orderState"));
			String infos[] = orderState.split("=");
			hylResponseVO.setStatus(infos[1]);
			String resMessage = result.substring(result.indexOf("responseMsg"),result.indexOf("&responseTime"));
			String message[] = resMessage.split("=");
			hylResponseVO.setResponseMsg(message[1]);
			hylResponseVO.setMessage(result);
			String resCode = result.substring(result.indexOf("responseCode"),result.indexOf("&responseMsg"));
			String resCodes[] = resCode.split("=");
			hylResponseVO.setResponseCode(resCodes[1]);
		}

		return hylResponseVO;
	}

	@Override
	public HYLResponseVO verifyQuery(String orderNo) {
		HYLResponseVO hylResponseVO = new HYLResponseVO();
		String resultStr = null;
		try {
			//获取数据对象
			Map<String,String> requestMap = getVerifyQueryMap(orderNo);
			//获取请求message
			String message = getMessage(requestMap);
			//封装参数
			NameValuePair[] param = {
					new NameValuePair("mode", "01"),    //01测试 02生产
					new NameValuePair("type","02"),     //01身份验证 02卡信息验证
					new NameValuePair("message", message)
			};
			log.info("好易联鉴权查询请求地址:"+ hylProperties.getQueryurl());
			//发送请求
			resultStr = sendRequest(param,hylProperties.getQueryurl());
			log.info("好易联鉴权查询返回加密报文",resultStr);
			if (StringUtils.isBlank(resultStr)){
				hylResponseVO.setResponseCode(MapUtil.INTF_ERR_CODE);
				hylResponseVO.setMessage("好易联鉴权查询请求错误");
				return hylResponseVO;
			}
			if(resultStr.split("\\|").length==2){
				String return2 = resultStr.split("\\|")[1];
				//错误原因
				hylResponseVO.setResponseCode(MapUtil.INTF_ERR_CODE);
				hylResponseVO.setResponseMsg(EncryDecryUtils.base64Decrypt(return2));
				return hylResponseVO;
			}
			//处理响应报文
			String return1 = resultStr.split("\\|")[0];
			String return2 = resultStr.split("\\|")[1];
			String return3 = resultStr.split("\\|")[2];
			//解析第二部分，获取原始报文 先解密base再解密3des
			String originalMsg  =  EncryDecryUtils.decryptFromBase64DES(hylProperties.getDes3Key(), return2);
			String result = null;
			result = URLDecoder.decode(originalMsg,"utf-8");
			log.info("好易联鉴权查询返回的报文明文是:"+result);
			//解析第三部分，获取原始签名
			String originalSign  =  EncryDecryUtils.base64Decrypt(return3);
			log.info("好易联鉴权查询返回的报文原始签名是:"+ originalSign);
			//报文验签
			boolean signFlag = verifySign(originalMsg,originalSign);
			hylResponseVO.setVerifySignFlag(signFlag);
			//获取验证状态
			if (StringUtils.isNotBlank(result)){
				String orderState = result.substring(result.indexOf("orderState"));
				String infos[] = orderState.split("=");
				hylResponseVO.setStatus(infos[1]);
			}
			hylResponseVO.setMessage(result);
			hylResponseVO.setResponseCode(MapUtil.INTF_SUC_CODE);
			hylResponseVO.setResponseMsg("好易联鉴权查询请求成功");
		}catch (Exception e){
			log.info("好易联鉴权查询请求错误："+e);
			hylResponseVO.setResponseCode(MapUtil.INTF_ERR_CODE);
			hylResponseVO.setResponseMsg("好易联鉴权查询失败");
			return hylResponseVO;
		}
		return hylResponseVO;
	}

	/**
	 * 封装鉴权请求数据对象
	 * @param request
	 * @return
	 */
	private Map<String, String> getVerifyMap(Map<String, String> request){
		Map<String, String> params = new HashMap<String, String>();
		params.put("idCardName", request.get("idCardName"));
		params.put("idCard",request.get("idCard"));
		params.put("bankCardNum",request.get("bankCardNum"));
		params.put("mobile",request.get("mobile"));
		params.put("mhtOrderNo", request.get("mhtOrderNo"));
		params.put("remarkes1", request.get("remark"));  //保留域1
		params.put("remarkes2", request.get("remark"));  //保留域2
		params.put("msgCode", request.get("msgCode"));    //短信验证码
		params.put("merchNo", hylProperties.getMerchNo());
		return params;
	}

	/**
	 * 封装鉴权查询请求数据对象
	 * @param orderNo
	 * @return
	 */
	private Map<String, String> getVerifyQueryMap(String orderNo){
		Map<String,String> requestMap = new HashMap<String, String>();
		requestMap.put("mode", "01");  //01测试 02生产
		requestMap.put("type", "02");  //01身份验证 02卡信息验证
		requestMap.put("mhtOrderNo", orderNo);
		return requestMap;
	}

	/**
	 * 封装message对象
	 * @param params
	 * @return
	 */
	private String getMessage(Map<String, String> params){
		String toRSAStr = FormDateReportConvertor.postFormLinkReport(params);
		log.info("好易联发送报文原文:"+toRSAStr);
		String message1 = "merchNo="+ hylProperties.getMerchNo();
		message1 = EncryDecryUtils.base64Encrypt(message1);
		String message2 = toRSAStr;
		message2 = EncryDecryUtils.encryptFromDESBase64(hylProperties.getDes3Key(),message2);// base64(3DES(报文原文)
		String message3 = EncryDecryUtils.base64Encrypt(EncryDecryUtils.md5(toRSAStr.toString().trim() +"&"+ hylProperties.getMd5Key()));//base64(MD5(报文原文+&+ md5Key))
		String message = message1+"|"+message2+"|"+message3;
		return message;
	}
	/**
	 * 发送请求
	 * @param param
	 * @return
	 */
	private String sendRequest(NameValuePair[] param,String url){
		String resultStr = null;
		try {
			HttpClient client = new HttpClient();
			Protocol myhttps=new Protocol("https",new MySSLProtocolSocketFactory(),443);
			Protocol.registerProtocol("https", myhttps);
			PostMethod post = new PostMethod(url);
			post.addRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
			post.setRequestBody(param);
			client.executeMethod(post);
			InputStream responseBody = post.getResponseBodyAsStream();
			InputStreamReader in = new InputStreamReader(responseBody, "utf-8");
			BufferedReader br = new BufferedReader(in);
			StringBuffer rets = new StringBuffer();
			String inputLine = "";
			while ((inputLine = br.readLine()) != null){
				rets.append(inputLine);
			}
			in.close();
			resultStr=rets.toString().trim();
		}catch (Exception e){
			log.info("好易联请求错误："+e);
		}
		return resultStr;
	}

	/**
	 * 验签
	 * @param originalMsg
	 * @param originalSign
	 * @return
	 */
	private boolean verifySign(String originalMsg, String originalSign){
		try {
			/**
			 * 获取到原始报文以后建议做一次trim去掉后面的空格，否则会验签不通过
			 **/
			String mySign = EncryDecryUtils.md5(URLDecoder.decode(originalMsg,"utf-8").trim()+"&"+ hylProperties.getMd5Key());//.trim() 很重要
			log.info("好易联商户生成的签名是:"+mySign);
			//对比签名是否验证通过
			if(originalSign.equals(mySign)){
				//签名验证通过
				log.info("好易联验证签名通过");
				return true;
			}else{
				log.info("好易联验证签名未通过");
				return false;
			}
		}catch (Exception e){
			log.info("好易联验证签名失败");
		}
		return false;
	}
}
